package com.tools.genxsd.store;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import com.tools.genxsd.entity.XsdBaseType;
import com.tools.genxsd.entity.XsdElement;
import com.tools.genxsd.entity.type.XsdAttributeType;
import com.tools.genxsd.entity.type.XsdDecimalType;
import com.tools.genxsd.entity.type.XsdStringType;
import com.tools.genxsd.store.factory.SimpTypeFactory;
import com.tools.genxsd.util.ExcelUtil;
import com.tools.genxsd.util.FilePathUtil;
import com.tools.genxsd.util.PatternUtil;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import static cn.hutool.core.text.StrPool.DELIM_END;
import static com.tools.genxsd.constant.BaseTypeConstant.*;
import static com.tools.genxsd.constant.RegexConstant.*;
import static com.tools.genxsd.constant.SysConstant.*;
import static com.tools.genxsd.constant.TypeNameConstant.*;

/**
 * @author: zhoubin
 * @date: 2022/11/11
 */
public class SimpleTypeStore {

    public static Map<String, XsdBaseType> baseTypeMap = new HashMap<>();

    static {
        initBaseType();
        initFileBaseType();
    }

    private static void initFileBaseType() {
        String baseTypePath = FilePathUtil.getBaseTypeFile();
        File baseTypeFile = null;
        if (CharSequenceUtil.isNotBlank(baseTypePath) && (baseTypeFile = new File(baseTypePath)).exists()) {
            try {
                ExcelUtil.praseExcel(baseTypeFile, workbook -> {
                    XSSFSheet sheet = workbook.getSheetAt(0);

                    int rowsNum = sheet.getPhysicalNumberOfRows();
                    for (int i = 1; i < rowsNum; i++) {
                        XSSFRow row = sheet.getRow(i);

                        if (Objects.isNull(row)) {
                            System.out.println("基本类型文件第" + i + "行出错");
                            continue;
                        }

                        String name = row.getCell(0).getStringCellValue();
                        String type = row.getCell(1).getStringCellValue().trim();
                        String val = row.getCell(2).getStringCellValue();

                        baseTypeMap.put(name, SimpTypeFactory.createType(name, type, val));
                    }
                });
            } catch (Exception e) {
                System.out.println("文件: " + baseTypeFile + "的基础类型生成失败");
                e.printStackTrace();
            }
        }
    }

    private static void initBaseType() {
        baseTypeMap.put(MAX_N_TEXT, new XsdStringType(MAX_N_TEXT, BASE_TYPE_STRING, MIN_LENGTH, MAX_LENGTH));
        baseTypeMap.put(LEI_IDENTIFIER, new XsdStringType(LEI_IDENTIFIER, BASE_TYPE_STRING, LEI_IDENTIFIER_REGEX));
        baseTypeMap.put(BICFIDEC2014_IDENTIFIER, new XsdStringType(BICFIDEC2014_IDENTIFIER, BASE_TYPE_STRING, BICFIDEC2014_IDENTIFIER_REGEX));
        baseTypeMap.put(BIC_IDENTIFIER, new XsdStringType(BIC_IDENTIFIER, BASE_TYPE_STRING, BIC_IDENTIFIER_REGEX));
        baseTypeMap.put(ISO_DATE_TIME, new XsdStringType(ISO_DATE_TIME, BASE_TYPE_DATETIME));
        baseTypeMap.put(ISO_DATE, new XsdStringType(ISO_DATE, BASE_TYPE_DATE));

        XsdAttributeType xsdAttributeType = new XsdAttributeType(ACTIVE_CURRENCY_AND_AMOUNT, CCY,
                XsdDecimalType.builder()
                        .name(ACTIVE_CURRENCY_AND_AMOUNT_SIMPLETYPE)
                        .baseType(BASE_TYPE_DECIMAL)
                        .fractionDigits("5")
                        .totalDigits("18")
                        .minInclusive("0").build(),
                new XsdStringType(ACTIVE_CURRENCY_CODE, BASE_TYPE_STRING, CURRENCY_CODE_REGEX),
                REQUIRED
                );
        baseTypeMap.put(ACTIVE_CURRENCY_AND_AMOUNT, xsdAttributeType);

        xsdAttributeType = new XsdAttributeType(ACTIVE_OR_HISTORIC_CURRENCY_AND_AMOUNT, CCY,
                XsdDecimalType.builder()
                        .name(ACTIVE_OR_HISTORIC_CURRENCY_AND_AMOUNT_SIMPLETYPE)
                        .baseType(BASE_TYPE_DECIMAL)
                        .fractionDigits("5")
                        .totalDigits("18")
                        .minInclusive("0").build(),
                new XsdStringType(ACTIVE_OR_HISTORIC_CURRENCY_CODE, BASE_TYPE_STRING, CURRENCY_CODE_REGEX),
                REQUIRED
        );
        baseTypeMap.put(ACTIVE_OR_HISTORIC_CURRENCY_AND_AMOUNT, xsdAttributeType);
        baseTypeMap.put(MAX_N_NUMERIC_TEXT, new XsdStringType(MAX_N_NUMERIC_TEXT, BASE_TYPE_STRING));

        baseTypeMap.put(PERCENTAGE_RATE, XsdDecimalType.builder()
                .name(PERCENTAGE_RATE)
                .baseType(BASE_TYPE_DECIMAL)
                .fractionDigits("10")
                .totalDigits("11").build());

        baseTypeMap.put(AMOUNT_RATE, XsdDecimalType.builder()
                .name(AMOUNT_RATE)
                .baseType(BASE_TYPE_DECIMAL)
                .fractionDigits("5")
                .totalDigits("18")
                .minInclusive("0").build());
    }

    public static XsdBaseType getTempType(XsdElement element) {
        XsdBaseType tempType = getTempType(element.getType());

        if (Objects.isNull(tempType)) {
            String typeDescribe = element.getTypeDescribe();

            tempType = SimpTypeFactory.createType(element.getType(), BASE_TYPE_STRING, typeDescribe);

            baseTypeMap.put(element.getType(), tempType);
        }

        return tempType;
    }

    /**
     * 获取报文类型
     * @param name
     * @return
     */
    public static XsdBaseType getTempType(String name) {

        XsdBaseType simpleType = baseTypeMap.get(name);

        if (Objects.nonNull(simpleType)) {
            return simpleType;
        }

        String maxSize = null;
        if (Objects.nonNull(maxSize = PatternUtil.isSimpleText(name))) {
            simpleType = ObjectUtil.clone(baseTypeMap.get(MAX_N_TEXT));
            simpleType.setMaxLength(maxSize);
            simpleType.setName(name);

        } else if (Objects.nonNull(maxSize = PatternUtil.isNumberText(name))){
            simpleType = ObjectUtil.clone(baseTypeMap.get(MAX_N_NUMERIC_TEXT));
            simpleType.setName(name);
            simpleType.setPattern(MAX_N_NUMERIC_PRE_REGEX + maxSize + DELIM_END);
        }

        return simpleType;
    }

}
